package blog

import (
	"dustbe/database"
	"dustbe/util"
	"errors"
	"html/template"
	"net/http"
	"strconv"

	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
)


func checkPrivilegeByPublisherId(c *gin.Context, publisherId int) error {
	session := sessions.Default(c)
	user := session.Get("user")
	if user != nil {
		opName := user.(string)
		// 检查是否和发布者是同一人
		dustUser, err := database.FindUserById(publisherId)
		publisherName := dustUser.Name
		if err != nil || opName != publisherName {
			return errors.New("权限不足")
		}
	} else {
		// 直接返回
		return errors.New("你还未登录！")
	}
	return nil
}

func checkPrivilegeByCommentId(c *gin.Context, commentId int) error {
	session := sessions.Default(c)
	user := session.Get("user")
	if user != nil {
		opName := user.(string)
		// 管理员不需要检查
		if opName == administraterName {
			return nil
		}
		// 检查是否和发布者是同一人
		publisherName, err := database.GetPublisherNameByCommentId(int64(commentId))
		if err != nil || opName != publisherName {
			return errors.New("权限不足")
		}
	} else {
		// 直接返回
		return errors.New("你还未登录！")
	}
	return nil
}

type PublishCommentPackage struct {
	BlogSeq 		int `json:"blogSeq"`
	PublisherId		int `json:"publisherId"`
	AtId 			int `json:"atId"`
	CreateTime 		int `json:"createTime"`
	Text 			string `json:"text"`
}


func PublishComment(c *gin.Context) {
	ok := util.LimitIpInterval(c, 5)
	if !ok {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": "你发送信息太频繁了！"})
		return
	}
	var publishCommentPackage PublishCommentPackage
	err := c.ShouldBindJSON(&publishCommentPackage)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"data": "请求体不正确"})
		return
	}

	publisherId := publishCommentPackage.PublisherId
	blogSeq := publishCommentPackage.BlogSeq
	atId := publishCommentPackage.AtId
	createTime := publishCommentPackage.CreateTime
	text := publishCommentPackage.Text


	// 检查权限
	err = checkPrivilegeByPublisherId(c, publisherId)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": err.Error()})
		return
	}


	err = util.CheckInputText(text, 200)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": err.Error()})
		return
	}

	// text = template.HTMLEscapeString(text)


	commendId, err := database.PublishComment(blogSeq, publisherId, atId, createTime, text)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": "不知道为什么，总之就是发布失败了"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "data": commendId})
}

type DeleteCommentPackage struct {
	CommentId int `json:"commentId"`
}


func DeleteComment(c *gin.Context) {
	var deleteCommentPackage DeleteCommentPackage
	err := c.ShouldBindJSON(&deleteCommentPackage)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"data": "请求体不正确"})
		return
	}
	commentId := deleteCommentPackage.CommentId

	// 检查权限
	err = checkPrivilegeByCommentId(c, commentId)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": err.Error()})
		return
	}

	err = database.DeleteComment(commentId)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": "不知道为什么，总之就是发布失败了"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "data": "删除成功"})
}


type ModifyCommentPackage struct {
	CommentId int `json:"commentId"`
	Text string `json:"text"`
}

func ModifyComment(c *gin.Context) {
	var modifyCommentPackage ModifyCommentPackage
	err := c.ShouldBindJSON(&modifyCommentPackage)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"data": "请求体不正确"})
		return
	}

	commentId := modifyCommentPackage.CommentId
	text := modifyCommentPackage.Text

	// 检查权限
	err = checkPrivilegeByCommentId(c, commentId)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": err.Error()})
		return
	}

	err = util.CheckInputText(text, 200)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": err.Error()})
		return
	}

	text = template.HTMLEscapeString(text)
	err = database.ModifyComment(commentId, text)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": "不知道为什么，总之就是发布失败了"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"code": 200, "data": "修改成功"})
}

type BlogComment struct {
	Id int64 `json:"id"`
	Text string `json:"text"`
	PublisherId int64 `json:"publisherId"`
	AtId int64 `json:"atId"`
	CreateTime int64 `json:"createTime"`
}

type CommentReturn struct {
	Comments []BlogComment `json:"comment"`
	DustUsers map[int64]database.DustUser `json:"dustUsers"`
}

func GetCommentsByBlogSeq(c *gin.Context) {
	blogSeq, _ := strconv.Atoi(c.Query("blogSeq"))
	tuples, err := database.GetCommentsByBlogSeq(blogSeq)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"code": 4001, "data": "不知道为什么，总之就是发布失败了"})
		return
	}

	comments := make([]BlogComment, len(tuples))
	dustUsers := make(map[int64]database.DustUser, 0)
	
	for index, tuple := range tuples {
		publisherPtr := tuple.PublisherNode
		_, ok := dustUsers[publisherPtr.Id]
		if !ok {
			dustUsers[publisherPtr.Id] = database.DustUser{
				Id: publisherPtr.Id,
				Name: publisherPtr.Props["name"].(string),
				ImgUrl: publisherPtr.Props["imgUrl"].(string),
			}
		}


		commentPtr := tuple.CommentNode
		blogComment := BlogComment{
			Id: commentPtr.Id,
			Text: commentPtr.Props["text"].(string),
			PublisherId: publisherPtr.Id,
			CreateTime: commentPtr.Props["createTime"].(int64),
		}

		atPtr := tuple.AtNode
		if atPtr != nil {
			blogComment.AtId = atPtr.Id
		} else {
			blogComment.AtId = -1
		}

		comments[index] = blogComment
	}

	commentReturn := CommentReturn{
		Comments: comments,
		DustUsers: dustUsers,
	}

	c.JSON(http.StatusOK, gin.H{"code": 200, "data": commentReturn})
}

func GetAdministraterName(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"code": 200, "data": "kirigaya"})
}